#pragma once

#include <iostream>
#include <string>
#include <cassert>
#include <pthread.h>


class thread
{
public:
    enum status_t 
    {
        NEW = 0,
        RUN,
    };
    typedef void* (*func_t)(void*);

private:
    std::string _name;
    func_t _func;
    void* _args;
    status_t _status;
    pthread_t _tid;
    static int _num;

public:
    thread()
    {}

    thread(int num, func_t func, void* args)
        : _name("thread" + std::to_string(num))
        , _func(func)
        , _args(args)
        , _status(NEW)
    {
        pthread_create(&_tid, nullptr, thread::routine, (void*)this);
        _status = RUN;
    }

    ~thread()
    {}

    static void* routine(void* args)
    {
        thread* ts = static_cast<thread*>(args);
        if (ts->_func)
        {
            return ts->_func(ts->_args);
        }
        return nullptr;
    }

    void join()
    {
        assert(pthread_join(_tid, nullptr) == 0);
    }

    void detach()
    {
        assert(pthread_detach(_tid) == 0);
    }

    pthread_t id()
    {
        return _tid;
    }

    std::string& name()
    {
        return _name;
    }

    status_t status()
    {
        return _status;
    }
};

